package com.d3works.apps.account.service.invoice.workflow.cancel;

import com.d3works.apps.account.db.Invoice;
import com.d3works.apps.account.db.InvoiceLine;
import com.d3works.apps.account.db.Move;
import com.d3works.apps.account.db.repo.InvoiceRepository;
import com.d3works.apps.account.db.repo.InvoiceTermRepository;
import com.d3works.apps.account.exception.AccountExceptionMessage;
import com.d3works.apps.account.service.BudgetService;
import com.d3works.apps.account.service.config.AccountConfigService;
import com.d3works.apps.account.service.invoice.InvoiceToolService;
import com.d3works.apps.account.service.invoice.workflow.WorkflowInvoice;
import com.d3works.apps.account.service.move.MoveCancelService;
import com.d3works.exception.D3worksException;
import com.d3works.exception.db.repo.TraceBackRepository;
import com.d3works.i18n.I18n;
import com.d3works.inject.Beans;
import com.google.inject.Inject;
import com.google.inject.persist.Transactional;

public class CancelState extends WorkflowInvoice {

  private WorkflowCancelService workflowService;
  private BudgetService budgetService;

  @Inject
  CancelState(WorkflowCancelService workflowService, BudgetService budgetService) {
    this.workflowService = workflowService;
    this.budgetService = budgetService;
  }

  @Override
  public void init(Invoice invoice) {
    this.invoice = invoice;
  }

  @Override
  public void process() throws D3worksException {

    workflowService.beforeCancel(invoice);

    if (invoice.getStatusSelect() == InvoiceRepository.STATUS_VENTILATED
        && invoice.getCompany().getAccountConfig().getAllowCancelVentilatedInvoice()) {
      cancelMove();
    }
    setStatus();
    if (Beans.get(AccountConfigService.class)
        .getAccountConfig(invoice.getCompany())
        .getIsManagePassedForPayment()) {
      setPfpStatus();
    }

    budgetService.updateBudgetLinesFromInvoice(invoice);

    for (InvoiceLine invoiceLine : invoice.getInvoiceLineList()) {
      invoiceLine.clearBudgetDistributionList();
    }

    workflowService.afterCancel(invoice);
  }

  @Transactional
  protected void setStatus() {

    invoice.setStatusSelect(InvoiceRepository.STATUS_CANCELED);
  }

  protected void cancelMove() throws D3worksException {

    if (invoice.getOldMove() != null) {
      throw new D3worksException(
          TraceBackRepository.CATEGORY_CONFIGURATION_ERROR,
          I18n.get(AccountExceptionMessage.INVOICE_CANCEL_1));
    }

    Move move = invoice.getMove();

    invoice.setMove(null);

    Beans.get(MoveCancelService.class).cancel(move);
  }

  protected void setPfpStatus() throws D3worksException {
    InvoiceToolService.setPfpStatus(invoice);
    invoice.setDecisionPfpTakenDate(null);

    invoice.getInvoiceTermList().stream()
        .filter(it -> it.getPfpValidateStatusSelect() != InvoiceTermRepository.PFP_STATUS_NO_PFP)
        .forEach(it -> it.setPfpValidateStatusSelect(InvoiceTermRepository.PFP_STATUS_AWAITING));
  }
}
